#ifndef ATOMIC_H
#define ATOMIC_H

inline __attribute__ ((always_inline))
int fetch_and_store(int *p, int val)
{
  int ret;

  asm __volatile__("xchgl %0, %1"
           : "=r"(ret), "=m"(*p)
           : "0"(val), "m"(*p)
           : "memory");

  return ret;
}

inline __attribute__ ((always_inline))
int compare_and_swap (int *p, int oldval, int newval)
{
  char ret;
  int readval;

  asm __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
	       : "=q" (ret), "=m" (*p), "=a" (readval)
	       : "r" (newval), "m" (*p), "a" (oldval)
	       : "memory");

  return ret;
}

/*
#define low_power_spin(p) asm __volatile__ ("L1:\n" \
                                            "move %0, %3;"\
                                            "move $0, %1;"\
                                            "move $0, %2;"\
                                            "monitor %3, %1, %2;" \
                                            "cmpl $1, (%0);" \
                                            "jnz L2;"\
                                            "move $0, %3;"\
                                            "move $0, %1;"\
                                            "mwait %3, %1;" \
                                            "cmpl $1, (%0);" \
                                            "jz L1;"\
                                            "L2:\n"\
           :\
           : "r" (p), "c" (0), "d" (0), "a" (0) \
           : "memory");
           */
           

#define low_power_spin(p) asm __volatile__ ("L1:\n" \
                                            "movl %0, %%eax;" \
                                            "movl $0, %1;" \
                                            "movl $0, %2;" \
                                            "monitor %%eax, %1, %2;" \
                                            "cmpl $1, (%0);" \
                                            "jnz L2;"\
                                            "movl $0, %%eax;" \
                                            "movl $0, %1;" \
                                            "mwait %%eax, %1;" \
                                            "cmpl $1, (%0);" \
                                            "jz L1;"\
                                            "L2:\n"\
           :\
           : "r" (p), "c" (0), "d" (0) \
           : "eax", "memory");

inline __attribute__ ((always_inline))
void spin (int *p)
{
    while (*p)
    {
        asm __volatile__ ("" : "=m" (*p) : "m" (*p));
    }
}


inline __attribute__ ((always_inline))
testandset (int *spinlock)
{
  long int ret;
  
  __asm__ __volatile__ (
      "xchgl %0, %1"
      : "=r" (ret), "=m" (*spinlock)
      : "0" (1), "m" (*spinlock)
      : "memory");
                    
  return ret;
}


//testing stuff

/*
inline __attribute__ ((always_inline))
void set_stuff (void)
{

 __asm__ __volatile__(
        "movl $0x1a0, %%eax;" \
        "or %%eax, 1 << 18;" \ 
        "movl %%eax, $0x1a0;"  
        : 
        : 
        : "eax", "memory");

}
*/



#endif // ifndef ATOMIC_H
